The object system works like the rest of OCaml (I wonder why it’s considered as some sort of legendary beast that would not obey the usual rules): No runtime type information, only safe upcasts.
Memory leaks are still possible because it is possible for a programmer to fail to “get rid of” a resource they don’t need any longer. Imagine, for example, that you are maintaining a data structure containing information you only need temporarily and you never removed stale data from the data structure.
What is not possible is to have use after free errors, or to leak memory that is no longer referenced/reachable by anything in the program.
If you compare to a dynamic language like Clojure, it would be difficult to catalog all of the errors that can’t happen in OCaml. (That’s not an insult–I’m a fan of Clojure, Common Lisp, etc.–but I recognize the tradeoffs.)
Accessing the “wrong” member of a Union in C is actually defined behavior, and undefined in C++. You have it backwards. The OCaml C runtime does just this to do bit pattern preserving transformations between types of the same size in a few places — it’s sanctioned to do this by the C standard.
It is, however, dangerous, and it’s indeed something that sum types in OCaml don’t permit.