Many people use the Shapes example, but that is in fact a dangerous one. The problem arises when you intuitively decide that a square is a subclass of rectangle.
When it comes to behavior, a square is more limited than a rectangle, breaking substitutability. For example, we could ask a rectangle object to change its height. If a square is a subclass of rectangle, that means we should be able to ask the same of a square. However, changing the height of a square would mean its not a square anymore! Of course, we could increase the width accordingly, but that's not what we would expect when we were to ask an object of declared type rectangle, which is actually a square underneath, to change its height.
It's called the Liskov substitution principle, and you should be aware of it when doing any serious OO development.
Squares are, of course a subset of rectangles, instead of a subclass. This is the difference between data-oriented and behaviour-oriented approaches.
Like Jon, I prefer Streams as an example. It's not difficult to explain, even to non-programmers, and its cleary behaviour-oriented, avoiding the counter-intuitivity of the shapes-example.