diff --git a/README.rst b/README.rst
index 82e03248556a004fe44a5bc29b122c8dbbc94c66..8e812f5fb8f3a930144b481d91dac159480a712b 100644
--- a/README.rst
+++ b/README.rst
@@ -302,6 +302,32 @@ Reset all the calls
 Wipe away the call history. Nobody will know.
 
 
+Call the original function
+--------------------------
+
+.. code-block:: python
+
+    result = obj.function.call_original('foo', bar='baz')
+
+
+Super, super useful if you want to use ``call_fake=`` to wrap a function
+and track or influence some part of it, but still want the original function
+to do its thing. For instance:
+
+.. code-block:: python
+
+    stored_results = []
+
+    def my_fake_function(*args, **kwargs):
+        kwargs['bar'] = 'baz'
+        result = obj.function.call_original(*args, **kwargs)
+        stored_results.append(result)
+
+        return result
+
+    agency.spy_on(obj.function, call_fake=my_fake_function)
+
+
 FAQ
 ===
 
diff --git a/kgb/spies.py b/kgb/spies.py
index b1ab5dddb0f32656dff6174b97a946ae70a0cf94..68b9b867d63106e6487b634a3a378e2eac6c67a4 100644
--- a/kgb/spies.py
+++ b/kgb/spies.py
@@ -203,7 +203,7 @@ class FunctionSpy(object):
     TYPE_UNBOUND_METHOD = 2
 
     _PROXY_METHODS = [
-        'called_with', 'last_called_with',
+        'call_original', 'called_with', 'last_called_with',
         'raised', 'last_raised', 'returned', 'last_returned',
         'raised_with_message', 'last_raised_with_message',
         'reset_calls', 'unspy',
@@ -377,8 +377,6 @@ class FunctionSpy(object):
             else:
                 self._set_method(self.owner, self.func_name, real_func)
 
-        self._real_func = real_func
-
         self.argspec = self._get_arg_spec(func)
 
         # If call_fake was provided, check that it's valid and has a
@@ -396,6 +394,9 @@ class FunctionSpy(object):
                 raise IncompatibleFunctionError(
                     self, func, self.argspec, call_fake, call_fake_argspec)
 
+        self._real_func = real_func
+        self._call_orig_func = self._clone_function(self.orig_func)
+
         if call_fake:
             self.func = call_fake
         elif call_original:
@@ -604,6 +605,42 @@ class FunctionSpy(object):
         if unregister:
             self.agency.spies.remove(self)
 
+    def call_original(self, *args, **kwargs):
+        """Call the original function being spied on.
+
+        The function will behave as normal, and will not trigger any spied
+        behavior or call tracking.
+
+        Args:
+            *args (tuple):
+                The positional arguments to pass to the function.
+
+            **kwargs (dict):
+                The keyword arguments to pass to the function.
+
+        Returns:
+            object:
+            The return value of the function.
+
+        Raises:
+            Exception:
+                Any exceptions raised by the function.
+        """
+        if self.func_type == self.TYPE_BOUND_METHOD:
+            return self._call_orig_func(self.owner, *args, **kwargs)
+        else:
+            if self.func_type == self.TYPE_UNBOUND_METHOD:
+                if not args or not isinstance(args[0], self.owner):
+                    raise TypeError(
+                        'The first argument to %s.call_original() must be '
+                        'an instance of %s.%s, since this is an unbound '
+                        'method.'
+                        % (self._call_orig_func.__name__,
+                           self.owner.__module__,
+                           self.owner.__name__))
+
+            return self._call_orig_func(*args, **kwargs)
+
     def called_with(self, *args, **kwargs):
         """Return whether the spy was ever called with the given arguments.
 
diff --git a/kgb/tests/base.py b/kgb/tests/base.py
index fa489b9648258bf949e591b35b4fe813432253f5..5341b84d44704ddfb31ca2a77050cb7cbbb676ff 100644
--- a/kgb/tests/base.py
+++ b/kgb/tests/base.py
@@ -13,20 +13,31 @@ from kgb.agency import SpyAgency
 
 class MathClass(object):
     def do_math(self, a=1, b=2, *args, **kwargs):
+        print(self)
+        assert isinstance(self, MathClass)
+
         return a + b
 
     def do_math_pos(self, a, b):
+        assert isinstance(self, MathClass)
+
         return a + b
 
     def do_math_mixed(self, a, b=2, *args, **kwargs):
+        assert isinstance(self, MathClass)
+
         return a + b
 
     @classmethod
     def class_do_math(cls, a=2, b=5, *args, **kwargs):
+        assert issubclass(cls, MathClass)
+
         return a * b
 
     @classmethod
     def class_do_math_pos(cls, a, b):
+        assert issubclass(cls, MathClass)
+
         return a * b
 
 
diff --git a/kgb/tests/test_function_spy.py b/kgb/tests/test_function_spy.py
index 308106fd2806639fc175651f8e34a940bb3caaf7..3ee8386af54c9fe1b6f5ce87387b49f6000826f0 100644
--- a/kgb/tests/test_function_spy.py
+++ b/kgb/tests/test_function_spy.py
@@ -1,6 +1,7 @@
 from __future__ import unicode_literals
 
 import inspect
+import re
 import types
 
 from kgb.errors import ExistingSpyError, IncompatibleFunctionError
@@ -21,10 +22,14 @@ def do_math_mixed(a, b=2, *args, **kwargs):
 
 
 def fake_do_math(self, a, b, *args, **kwargs):
+    assert isinstance(self, MathClass)
+
     return a - b
 
 
-def fake_class_do_math(self, a, b, *args, **kwargs):
+def fake_class_do_math(cls, a, b, *args, **kwargs):
+    assert issubclass(cls, MathClass)
+
     return a - b
 
 
@@ -38,17 +43,25 @@ def fake_something_awesome():
 
 class AdderObject(object):
     def func(self):
+        assert isinstance(self, AdderObject)
+
         return [self.add_one(i) for i in (1, 2, 3)]
 
     def add_one(self, i):
+        assert isinstance(self, AdderObject)
+
         return i + 1
 
     @classmethod
     def class_func(cls):
+        assert cls is AdderObject
+
         return [cls.class_add_one(i) for i in (1, 2, 3)]
 
     @classmethod
     def class_add_one(cls, i):
+        assert issubclass(cls, AdderObject)
+
         return i + 1
 
 
@@ -943,6 +956,173 @@ class FunctionSpyTests(TestCase):
         self.assertTrue(AdderObject.class_func.called)
         self.assertEqual(result, [2, 3, 4])
 
+    def test_call_original_with_orig_func_and_function(self):
+        """Testing FunctionSpy.call_original with spy on function set up using
+        call_original=True
+        """
+        self.agency.spy_on(do_math,
+                           call_original=True)
+
+        result = do_math.call_original(10, 20)
+        self.assertEqual(result, -10)
+
+        self.assertFalse(do_math.called)
+
+    def test_call_original_with_orig_func_and_bound_method(self):
+        """Testing FunctionSpy.call_original with spy on bound method set up
+        using call_original=True
+        """
+        obj = AdderObject()
+        self.agency.spy_on(obj.add_one,
+                           call_original=True)
+
+        result = obj.add_one.call_original(5)
+        self.assertEqual(result, 6)
+
+        self.assertFalse(obj.add_one.called)
+
+    def test_call_original_with_orig_func_and_unbound_method(self):
+        """Testing FunctionSpy.call_original with spy on unbound method set up
+        using call_original=True
+        """
+        self.agency.spy_on(AdderObject.add_one,
+                           call_original=True)
+
+        obj = AdderObject()
+        result = obj.add_one.call_original(obj, 5)
+        self.assertEqual(result, 6)
+
+        self.assertFalse(AdderObject.add_one.called)
+        self.assertFalse(obj.add_one.called)
+
+    def test_call_original_with_orig_func_and_classmethod(self):
+        """Testing FunctionSpy.call_original with spy on classmethod set up
+        using call_original=True
+        """
+        self.agency.spy_on(AdderObject.class_add_one,
+                           call_original=True)
+
+        result = AdderObject.class_add_one.call_original(5)
+        self.assertEqual(result, 6)
+
+        self.assertFalse(AdderObject.class_add_one.called)
+
+    def test_call_original_with_no_func_and_function(self):
+        """Testing FunctionSpy.call_original with spy on function set up using
+        call_original=False
+        """
+        self.agency.spy_on(do_math)
+
+        result = do_math.call_original(10, 20)
+        self.assertEqual(result, -10)
+
+        self.assertFalse(do_math.called)
+
+    def test_call_original_with_no_func_and_bound_method(self):
+        """Testing FunctionSpy.call_original with spy on bound method set up
+        using call_original=False
+        """
+        obj = MathClass()
+        self.agency.spy_on(obj.do_math)
+
+        result = obj.do_math.call_original(10, 20)
+        self.assertEqual(result, 30)
+
+        self.assertFalse(obj.do_math.called)
+
+    def test_call_original_with_no_func_and_unbound_method(self):
+        """Testing FunctionSpy.call_original with spy on unbound method set up
+        using call_original=False
+        """
+        self.agency.spy_on(MathClass.do_math)
+
+        obj = MathClass()
+        result = obj.do_math.call_original(obj, 10, 20)
+        self.assertEqual(result, 30)
+
+        self.assertFalse(MathClass.do_math.called)
+        self.assertFalse(obj.do_math.called)
+
+    def test_call_original_with_no_func_and_classmethod(self):
+        """Testing FunctionSpy.call_original with spy on classmethod set up
+        using call_original=False
+        """
+        self.agency.spy_on(MathClass.class_do_math)
+
+        result = MathClass.class_do_math.call_original(10, 20)
+        self.assertEqual(result, 200)
+
+        self.assertFalse(MathClass.class_do_math.called)
+
+    def test_call_original_with_fake_func_and_function(self):
+        """Testing FunctionSpy.call_original with spy on function set up using
+        call_fake=
+        """
+        self.agency.spy_on(do_math,
+                           call_fake=fake_do_math)
+
+        result = do_math.call_original(10, 20)
+        self.assertEqual(result, -10)
+
+        self.assertFalse(do_math.called)
+
+    def test_call_original_with_fake_func_and_bound_method(self):
+        """Testing FunctionSpy.call_original with spy on bound method set up
+        using call_fake=
+        """
+        obj = MathClass()
+        self.agency.spy_on(obj.do_math,
+                           call_fake=fake_do_math)
+
+        result = obj.do_math.call_original(10, 20)
+        self.assertEqual(result, 30)
+
+        self.assertFalse(obj.do_math.called)
+
+    def test_call_original_with_fake_func_and_unbound_method(self):
+        """Testing FunctionSpy.call_original with spy on unbound method set up
+        using call_fake=
+        """
+        self.agency.spy_on(MathClass.do_math,
+                           call_fake=fake_do_math)
+
+        obj = MathClass()
+        result = obj.do_math.call_original(obj, 10, 20)
+        self.assertEqual(result, 30)
+
+        self.assertFalse(MathClass.do_math.called)
+        self.assertFalse(obj.do_math.called)
+
+    def test_call_original_with_fake_func_and_classmethod(self):
+        """Testing FunctionSpy.call_original with spy on classmethod set up
+        using call_fake=
+        """
+        self.agency.spy_on(MathClass.class_do_math,
+                           call_fake=fake_class_do_math)
+
+        result = MathClass.class_do_math.call_original(10, 20)
+        self.assertEqual(result, 200)
+
+        self.assertFalse(MathClass.class_do_math.called)
+
+    def test_call_original_with_unbound_method_no_instance(self):
+        """Testing FunctionSpy.call_original with spy on unbound method set up
+        using call_original=True without passing instance
+        """
+        self.agency.spy_on(AdderObject.add_one,
+                           call_original=True)
+
+        obj = AdderObject()
+
+        message = re.escape(
+            'The first argument to add_one.call_original() must be an '
+            'instance of kgb.tests.test_function_spy.AdderObject, since this '
+            'is an unbound method.'
+        )
+
+        with self.assertRaisesRegexp(TypeError, message):
+            obj.add_one.call_original(5)
+
     def test_called(self):
         """Testing FunctionSpy.called"""
         obj = MathClass()
