So, the gist of the difference is this: object-oriented programming is, at its core, about late binding. Specifically, delaying decisions about what code will run when until run-time. But there's still some wiggle room to decide how late certain decisions are made. Most mainstream object-oriented languages like Java and C# more-or-less wait until the start of run-time to decide, but at that point the mapping from argument type to which code is run is pretty much settled. (This isn't necessarily 100% true, but it's the general rule.)
In a system that uses message passing, it's pushed even later, to method invocation time. Basically, each object (actor, whatever) gets to decide what code will be executed to handle a message every time it receives a new message, even for messages of the same type. In practice, most the time it's always the same code. But the point is that this level of dynamicism is a first-class language feature and not just a thing you can accomplish with hacks.