All you need to do is define an arbitrary stable ordering. (Your "object birth time" is
one such idea, but I don't think it is stored).
Method1:
For any two objects of the same exact type, you can define such an ordering by comparing
their individual fields. If all fields are identical, the objects are equal; if not,
some field f is different and you can define the ordering based on the underlying type.
If you have two objects with different types, simply use the type name to define the order; the
one whose name is lexicographically smaller is "less than". You can implement a compare-per-type
(might be a lot of work) or you can likely implement a generic compare the uses reflection
to enumerate field names and types (to enable type-specific compares), although this might
be pretty slow.
Method2:
Any time you call your comparator, cache any object not yet encountered in a linear array.
Any objects thus compared now have a index position in the array; o1 < o2 if the index(o1) < index(o2).
You might need a hash table to associate assigned index positions with cached objects.
Method3:
If you are working with a specific subset of the objects, and there's a canonical
spanning tree, then number each edge of the spanning tree such that children arcs
have unique numbers. Then o1 < o2 if the path to o1 from the root of the spanning tree,
is less than the path to o2.