This will happen because of the way memory works in C#. Each class object is actually a pointer to an object in memory - when you assign one variable to another, you're still using the same pointer and, thus, modifying the same data when you make a change to one object.
Technically speaking, if you made all your objects structs, they would copy around just fine, because structures are values types and thus pass copies. This, however, is highly inadvisable because it limits usage, particularly with polymorphism, and is a bad idea for memory management of objects with lots of members.
The BEST way to solve this is to implement a function on class Dog which allows you to copy the data into a new Dog object. Thus, you would call
Dog buster = jake.Clone();
buster.Name = "Buster";
And in Clone, copy all properties from the current Dog object into a new Dog object.
EDIT: Going back to c++ roots, it's also common to implement a "Copy constructor" which takes a parameter of the same type in and makes a deep copy. IE
Dog jake = new Dog() { Name = "Jake" };
Dog buster = new Dog(jake) { Name = "Buster" };
NOTE: The above syntax uses the curly brackets, which allows you to set properties and fields from your class as soon as you create it. While technically compiler sugar, it is very good at making instantiation calls a lot more succinct