id in Objective-C is not eactly the same as void * in C.
From Apple's "The Objective-C Programming Language":
typedef struct objc_object { Class isa; } *id;
Which means, id is a pointer to an objc_object structure, which is different from a pointer to void.
Every object thus has an isa variable that tells it of what class it is an instance. Since the Class type is itself declared as a pointer.
typedef struct objc_class *Class;
And regarding, how the program tell the class during method invocation?, here is this from the same programming guide cited above:
The isa instance variable identifies the object's class -what kind of object it is. Objects with the same behavior (methods) and the same kinds of data (instance variables) are members of the same class.
Objects are thus dynamically typed at runtime. Whenever it needs to, the runtime system can find the exact class that an object belongs to, just by asking the object. (To learn more about the runtime, see Objective-C Runtime Programming Guide.)
According to the guide, id, nil, and other basic types of Objective-C are defined in the header file objc/objc.h.